/**
 * 
 */
package group.anglers.om.core.persistence.impls;

import group.anglers.om.core.commons.StringUtils;
import group.anglers.om.core.persistence.serialization.Column;
import group.anglers.om.core.persistence.serialization.Composite;
import group.anglers.om.core.persistence.serialization.impl.ModelSerialization;

import java.util.ArrayList;
import java.util.List;

/**
 * @author an.pham
 *
 */
class CRUDQueryBuilder {
	private static final String INSERT_STATEMENT = "INSERT INTO";
	private static final String INSERT_VALUES_STATEMENT = "VALUES";
	
	private static final String UPDATE_STATEMENT = "UPDATE";
	private static final String DELETE_STATEMENT = "DELETE FROM";
	
	private static final String SELECT_ALL_STATEMENT = "SELECT * FROM";
	private static final String WHERE_STATEMENT = "WHERE";
	private static final String AND_STATEMENT = "AND";
	private static final String EQUALS_STATEMENT = "=";
	private static final String SET_STATEMENT = "SET";
	
	public static String buildInsertQuery(ModelSerialization modelSerialization){
		// builder query for insert statement
		StringBuilder queryBuilder = new StringBuilder();
		// builder for parameters block
		StringBuilder paramsBuilder = new StringBuilder();
		// append insert statement into queryBuilder
		queryBuilder.append(INSERT_STATEMENT)
			.append(StringUtils.BLANK)
			.append(modelSerialization.getTableName())
			.append(StringUtils.BLANK)
			.append(StringUtils.OPEN_PARENTHESIS);
		// append open parenthesis into paramsBuilder
		paramsBuilder.append(StringUtils.OPEN_PARENTHESIS);
		/* define all columns which needed for creating a insert query statement */
		List<Column> columns = new ArrayList<Column>();
		
		int loop = 0;
		Column column = null;
		/* get primary column */
		if(modelSerialization.getPrimaryKey() instanceof Composite){
			Composite composite = (Composite) modelSerialization.getPrimaryKey();
			
			columns.addAll(composite.getColumns());
		}else {
			column = (Column) modelSerialization.getPrimaryKey();
			columns.add(column);
		}
		/* get normal columns */
		columns.addAll(modelSerialization.getColumns());
		
		loop = columns.size();
		
		for(int i=0; i < loop; i ++){
			column = columns.get(i);
			// append field name into queryBuilder
			queryBuilder.append(column.getName());
			// append question mark into paramsBuilder
			paramsBuilder.append(StringUtils.QUESTION_MARK);
			
			if(i + 1 < loop){
				// append comma and blank between field names
				queryBuilder.append(StringUtils.COMMA).append(StringUtils.BLANK);
				// append comma and blank between question mark symbols
				paramsBuilder.append(StringUtils.COMMA).append(StringUtils.BLANK);
			}
		}
		// append close parenthesis into paramsBuilder
		paramsBuilder.append(StringUtils.CLOSE_PARENTHESIS);
		// append close parenthesis into queryBuilder
		queryBuilder.append(StringUtils.CLOSE_PARENTHESIS);
		queryBuilder.append(StringUtils.BLANK);
		queryBuilder.append(INSERT_VALUES_STATEMENT);
		queryBuilder.append(StringUtils.BLANK);
		
		queryBuilder.append(paramsBuilder.toString());	
		
		return queryBuilder.toString();
	}
	
	public static String buildUpdateQuery(ModelSerialization modelSerialization){
		// builder query for update statement
		StringBuilder updateBuilder = new StringBuilder();
		// builder query for where statement
		StringBuilder whereBuilder = new StringBuilder();
		
		updateBuilder
			.append(UPDATE_STATEMENT)
			.append(StringUtils.BLANK)
			.append(modelSerialization.getTableName())
			.append(StringUtils.BLANK)
			.append(SET_STATEMENT)
			.append(StringUtils.BLANK);
		
		whereBuilder
			.append(WHERE_STATEMENT)
			.append(StringUtils.BLANK);
		
		int loop = 0;
		Column column = null;
		/* get primary column */
		if(modelSerialization.getPrimaryKey() instanceof Composite){
			Composite composite = (Composite) modelSerialization.getPrimaryKey();
			
			loop = composite.getColumns().size();
			
			for(int i=0; i < loop; i ++){
				column = composite.getColumns().get(i);
				
				whereBuilder
				.append(column.getName())
				.append(EQUALS_STATEMENT)
				.append(StringUtils.QUESTION_MARK)
				.append(StringUtils.BLANK);
				
				if(i + 1  < loop){
					whereBuilder
					.append(AND_STATEMENT)
					.append(StringUtils.BLANK);
				}
				
			}
		}else {
			column = (Column) modelSerialization.getPrimaryKey();
			
			whereBuilder
			.append(column.getName())
			.append(EQUALS_STATEMENT)
			.append(StringUtils.QUESTION_MARK);
		}
		/* get normal columns */
		loop = modelSerialization.getColumns().size();
		
		for(int i=0; i < loop; i ++){
			column = modelSerialization.getColumns().get(i);

			updateBuilder
			.append(column.getName())
			.append(EQUALS_STATEMENT)
			.append(StringUtils.QUESTION_MARK);
			
			if(i + 1 < loop){
				updateBuilder
				.append(StringUtils.COMMA)
				.append(StringUtils.BLANK);
			}
		}
		
		return updateBuilder.append(StringUtils.BLANK).append(whereBuilder.toString()).toString();
	}
	
	public static String buildDeleteQuery(ModelSerialization modelSerialization){
		// builder query for delete statement
		StringBuilder queryBuilder = new StringBuilder();
		queryBuilder.append(DELETE_STATEMENT)
		.append(StringUtils.BLANK)
		.append(modelSerialization.getTableName())
		.append(StringUtils.BLANK)
		.append(WHERE_STATEMENT)
		.append(StringUtils.BLANK);
		
		int loop = 0;
		Column column = null;
		/* get primary column */
		if(modelSerialization.getPrimaryKey() instanceof Composite){
			Composite composite = (Composite) modelSerialization.getPrimaryKey();
			
			loop = composite.getColumns().size();
			
			for(int i=0; i < loop; i ++){
				column = composite.getColumns().get(i);
				
				queryBuilder
				.append(column.getName())
				.append(EQUALS_STATEMENT)
				.append(StringUtils.QUESTION_MARK)
				.append(StringUtils.BLANK);
				
				if(i + 1  < loop){
					queryBuilder
					.append(AND_STATEMENT)
					.append(StringUtils.BLANK);
				}
				
			}
		}else {
			column = (Column) modelSerialization.getPrimaryKey();
			
			queryBuilder
			.append(column.getName())
			.append(EQUALS_STATEMENT)
			.append(StringUtils.QUESTION_MARK);
		}
		
		return queryBuilder.toString();
	}
	
	public static String buildFindByPKQuery(ModelSerialization modelSerialization){
		// builder query for find by PK statement
		StringBuilder queryBuilder = new StringBuilder();
		
		queryBuilder.append(SELECT_ALL_STATEMENT).append(StringUtils.BLANK).append(modelSerialization.getTableName());
		queryBuilder.append(StringUtils.BLANK).append(WHERE_STATEMENT).append(StringUtils.BLANK);
		
		/* define all columns which needed for creating a insert query statement */
		List<Column> columns = new ArrayList<Column>();
		Column column = null;
		/* get primary column */
		if(modelSerialization.getPrimaryKey() instanceof Composite){
			Composite composite = (Composite) modelSerialization.getPrimaryKey();
			
			columns.addAll(composite.getColumns());
		}else {
			column = (Column) modelSerialization.getPrimaryKey();
			columns.add(column);
		}
		
		int loop = columns.size();
		
		for(int i=0; i < loop; i ++){
			column = columns.get(i);
			// append field name into queryBuilder
			queryBuilder.append(column.getName()).append(EQUALS_STATEMENT).append(StringUtils.QUESTION_MARK);
			
			if(i + 1 < loop){
				// append comma and blank between field names
				queryBuilder.append(StringUtils.BLANK).append(AND_STATEMENT).append(StringUtils.BLANK);
			}
		}
		
		return queryBuilder.toString();
	}
	
	public static String buildFindAllPKQuery(ModelSerialization modelSerialization){
		// builder query for find by PK statement
		StringBuilder queryBuilder = new StringBuilder();
		
		queryBuilder.append(SELECT_ALL_STATEMENT).append(StringUtils.BLANK).append(modelSerialization.getTableName());
		
		return queryBuilder.toString();
	}
	
}
